package com.imooc.liu.shiroimooc.config;

import com.imooc.liu.shiroimooc.realm.AuthRealm;
import com.imooc.liu.shiroimooc.realm.MyCredentialsMatcher;
import org.apache.shiro.cache.MemoryConstrainedCacheManager;
import org.apache.shiro.mgt.DefaultSecurityManager;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.LinkedHashMap;

/**
 * shiro配置类
 *
 * @author liuwj3
 */
@Configuration
public class ShiroConfiguration {
    @Bean("shiroFilter")
    public ShiroFilterFactoryBean shiroFilter(@Qualifier("securityManager") SecurityManager securityManager) {
        ShiroFilterFactoryBean bean = new ShiroFilterFactoryBean();
        bean.setSecurityManager(securityManager);

        // 登陆页面
        bean.setLoginUrl("/login");
        // 访问成功页面
        bean.setSuccessUrl("/index");
        // 认证未通过页面
        bean.setUnauthorizedUrl("/unauthorized");

        // 定义一个拦截器链
        // key:正则表达式，代表我们访问的请求
        // value:代表我们使用什么样的拦截器
        LinkedHashMap<String, String> filterChainDefinitionMap = new LinkedHashMap<>();


        /**
         * 拦截器器名称设置来源于DefaultFilter.class
         * anon:匿名访问
         * authc:form表单验证
         * logout:注销拦截器
         * perms:权限验证拦截器
         * roles：角色验证拦截器
         * user:(UserFilter.class);
         */

        // 注意：下面这些key可以是页面名称，也可以说@RequestMapping上的名称
        // index页面必须登陆
        filterChainDefinitionMap.put("/index", "authc");
        // login页面不需要任何校验
        filterChainDefinitionMap.put("/login", "anon");
        filterChainDefinitionMap.put("/loginUser", "anon");
        // 角色控制，访问admin需要admin角色（RolesAuthorizationFilter过滤器）
        filterChainDefinitionMap.put("/admin", "roles[admin]");
        // 权限控制，（PermissionsAuthorizationFilter过滤器）
        filterChainDefinitionMap.put("/myedit", "perms[edit]");

        filterChainDefinitionMap.put("/druid/**", "anon");
        //拦截其它全部的借口，user过滤器（验证是否登陆过用户）
        filterChainDefinitionMap.put("/**", "user");

        bean.setFilterChainDefinitionMap(filterChainDefinitionMap);
        return bean;

    }

    @Bean("securityManager")
    public SecurityManager securityManager(@Qualifier("authRealm") AuthRealm authRealm) {
        DefaultWebSecurityManager manager = new DefaultWebSecurityManager();
        manager.setRealm(authRealm);
        return manager;
    }

    @Bean("authRealm")
    public AuthRealm authRealm(@Qualifier("myCredentialsMatcher") MyCredentialsMatcher myCredentialsMatcher) {
        AuthRealm authRealm = new AuthRealm();
        authRealm.setCacheManager(new MemoryConstrainedCacheManager());
        // 使用内存中缓存，相关认证授权的东西缓存
        authRealm.setCredentialsMatcher(myCredentialsMatcher);
        return authRealm;
    }

    @Bean("myCredentialsMatcher")
    public MyCredentialsMatcher myCredentialsMatcher() {
        return new MyCredentialsMatcher();
    }


    /**
     * spring与shiro的关联处理，设置spring使用的securityManager
     *
     * @param securityManager
     * @return
     */
    @Bean
    public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(@Qualifier("securityManager") SecurityManager securityManager) {
        AuthorizationAttributeSourceAdvisor advisor = new AuthorizationAttributeSourceAdvisor();
        advisor.setSecurityManager(securityManager);
        return advisor;
    }

    @Bean
    public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator() {
        DefaultAdvisorAutoProxyCreator creator = new DefaultAdvisorAutoProxyCreator();
        // 设置使用代理
        creator.setProxyTargetClass(true);
        return creator;
    }
}
